package m

import (
	"GameServer/Common/data"
	"GameServer/Common/utils"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	"sync"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"
)

// jackpot活动
type JActiv struct {
	BaseM
	Uid               int64               `bson:"_id" json:"_id"`                             // id
	ActivID           int64               `bson:"activID" json:"activID"`                     // 活动id
	GoodLst           map[int64]*BaseIdKV `bson:"goodLst" json:"goodLst"`                     // 路盘上的所有道具 map的key是轮盘id id:轮盘id key:道具id val:道具数量
	GoodNormal        map[int64]*BaseIdKV `bson:"goodNormal" json:"goodNormal"`               // 轮盘上的普通道具 id:轮盘id key:道具id val:道具数量
	TimeInterval      map[int64]int64     `bson:"timeInterval" json:"timeInterval"`           // 派奖时间间隔
	Threshold         map[int64]*BaseKV   `bson:"threshold" json:"threshold"`                 // 基础奖金和派发奖金
	IncrGoldSlotScale map[int64]int64     `bson:"incrGoldSlotScale" json:"incrGoldSlotScale"` // 老虎机总产出金币比例
	IncrGoldPerMinute map[int64]int64     `bson:"incrGoldPerMinute" json:"incrGoldPerMinute"` // 每分钟增加金币

	BeginTime int64 `bson:"beginTime" json:"beginTime"` // 活动开始时间
	EndTime   int64 `bson:"endTime" json:"endTime"`     // 活动结束时间

	JackpotX int64 `bson:"jackpotX" json:"jackpotX"`
}

// jackpot玩家
type JGamer struct {
	BaseM
	Uid         bson.ObjectId `bson:"_id" json:"_id"`                 // 玩家id
	Name        string        `bson:"name" json:"name"`               // 玩家名称
	Head        string        `bson:"head" json:"head"`               // 玩家头像
	AvatarFrame int64         `bson:"avatarFrame" json:"avatarFrame"` // 玩家头像框

	Amount int64 `bson:"amount" json:"amount"` // 获取大奖金额
	Jtype  int64 `bson:"jtype" json:"jtype"`   // 大奖类型
	Time   int64 `bson:"time" json:"time"`     // 获奖时间
}

// jackpot小组
type JGroup struct {
	BaseM
	Uid    int64             `bson:"_id" json:"_id"`       // 小组id
	MBonus map[int64]*JBonus `bson:"mBonus" json:"mBonus"` // 大奖信息
	rw     sync.RWMutex
}

// 大奖信息
type JBonus struct {
	BonusId int64 `bson:"bonusId" json:"bonusId"` // 大奖id
	Plate   int64 `bson:"plate" json:"plate"`     // 轮盘id
	Amount  int64 `bson:"amount" json:"amount"`   // 大奖金额
	Time    int64 `bson:"time" json:"time"`       // 大奖重置时间
	State   int64 `bson:"state" json:"state"`     // 大奖状态，0.不能领取 1.可领取
}

// jackpot活动：创建
func NewJActiv() cache.EntryI {
	return &JActiv{}
}

// jackpot活动：保存信息
func (this *JActiv) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("JActiv", bson.M{"_id": this.Uid}, this)
	return
}

// jackpot活动：加载
func (this *JActiv) Load(key interface{}) (err error) {
	switch key.(type) {
	case int64:
		this.Uid = key.(int64)
	default:
		log.WithFields(log.Fields{
			"method": "JActiv_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return this.LoadData()
}

// jackpot活动：加载数据
func (this *JActiv) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("JActiv", bson.M{"_id": this.Uid}, nil, &this)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}
	return
}

// jackpot活动：更新数据
func (this *JActiv) Update(val *JActiv) {
	Cache.Put("JActiv", val.Uid, val)
	val.UpdateData()
}

func GetJActiv(uid int64) (r *JActiv) {
	v, _ := Cache.Get("JActiv", uid)
	return v.(*JActiv)
}

func DelJActiv(uid int64) (err error) {
	Cache.Remove("JActiv", uid)
	return dbmodule.MgoDB.GameDB.Remove("JActiv", bson.M{"_id": uid})
}

// jackpot玩家：创建
func NewJGamer() cache.EntryI {
	return &JGamer{}
}

// jackpot玩家：保存信息
func (this *JGamer) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("JGamer", bson.M{"_id": this.Uid}, this)
	return
}

// jackpot玩家：加载
func (this *JGamer) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		this.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		this.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "JGamer_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return this.LoadData()
}

// jackpot玩家：加载数据
func (this *JGamer) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("JGamer", bson.M{"_id": this.Uid}, nil, &this)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}
	return
}

// jackpot玩家：更新数据
func (this *JGamer) Update(val *JGamer) {
	Cache.Put("JGamer", val.Uid.Hex(), val)
	val.UpdateData()
}

// jackpot玩家：获取数据
func GetJGamer(uid string) (r *JGamer) {
	v, _ := Cache.Get("JGamer", uid)
	return v.(*JGamer)
}

// jackpot小组：创建
func NewJGroup() cache.EntryI {
	return &JGroup{
		MBonus: make(map[int64]*JBonus),
	}
}

// jackpot小组：保存信息
func (this *JGroup) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("JGroup", bson.M{"_id": this.Uid}, this)
	return
}

// jackpot小组：加载
func (this *JGroup) Load(key interface{}) (err error) {
	switch key.(type) {
	case int64:
		this.Uid = key.(int64)
	default:
		log.WithFields(log.Fields{
			"method": "JGroup_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return this.LoadData()
}

// jackpot小组：加载数据
func (this *JGroup) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("JGroup", bson.M{"_id": this.Uid}, nil, &this)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}
	return
}

// jackpot小组：更新数据
func (this *JGroup) Update(val *JGroup) {
	Cache.Put("JGroup", val.Uid, val)
	val.UpdateData()
}

// jackpot小组：获取数据
func GetJGroup(uid int64) (r *JGroup) {
	v, _ := Cache.Get("JGroup", uid)
	return v.(*JGroup)
}

// jackpot小组：获取大奖信息
func (this *JGroup) GetBonus() (r map[int64]int64) {
	this.rw.RLock()
	defer this.rw.RUnlock()
	r = make(map[int64]int64)
	for key, val := range this.MBonus {
		r[key] = val.Amount
	}
	return
}

// 获取彩金状态
func (this *JGroup) GetBonusState() bool {
	this.rw.RLock()
	defer this.rw.RUnlock()

	for _, val := range this.MBonus {
		if val.State == 1 {
			return true
		}
	}
	return false
}

// jackpot小组：抽奖
func (this *JGroup) LuckDraw(threshold map[int64]*BaseKV, goodLst map[int64]*BaseIdKV, weights []data.WeightV, jTid int64) (r BaseKV, plate int64) {
	this.rw.Lock()
	defer this.rw.Unlock()
	for _, val := range this.MBonus {
		if val.State == 1 {
			continue
		}

		// 大奖状态为0，把权重改为0
		for _, item := range weights {
			if utils.Int64(item.Value) == val.Plate {
				item.Weight = 0
				break
			}
		}
	}
	weight := utils.RandomWeight(weights)
	plate = utils.Int64(weight.Value)
	var ldgood *BaseIdKV // 抽中的奖
	if val, ok := goodLst[plate]; ok {
		ldgood = val
	}
	r.Key = ldgood.Key
	// gm指定大奖
	if jTid > 0 {
		if val, ok := this.MBonus[jTid]; ok && val.State == 1 {
			r.Key = jTid
		}
		for _, item := range goodLst {
			if jTid == item.Key {
				plate = item.Id
			}
		}
	}
	// 抽中的是大奖，将大奖状态置位0
	if val, ok := this.MBonus[r.Key]; ok {
		val.State = 0
		r.Val = val.Amount
		valT, _ := threshold[r.Key]
		val.Amount = valT.Key // 领取大奖后，金额设为初始值。
		this.Update(this)
	} else {
		r.Val = ldgood.Val
	}
	return
}

func (this *JGroup) NormalLuckDraw(threshold map[int64]*BaseKV, goodLst map[int64]*BaseIdKV, weights []data.WeightV) (r BaseKV, plate int64) {
	weight := utils.RandomWeight(weights)
	plate = utils.Int64(weight.Value)
	var ldgood *BaseIdKV // 抽中的奖
	if val, ok := goodLst[plate]; ok {
		ldgood = val
	}
	r.Key = ldgood.Key
	r.Val = ldgood.Val
	return
}

// jackpot小组：添加钱
func (this *JGroup) AddBonus(incrGold map[int64]int64, timeInterval map[int64]int64, threshold map[int64]*BaseKV) {
	this.rw.Lock()
	defer this.rw.Unlock()
	nowUnix := utils.TNow().Unix()
	for key, val := range this.MBonus {
		val.Amount += incrGold[key] // 累计金额
		// 时间超过派奖时间间隔 并且 金额超过派奖金额
		if nowUnix-val.Time >= timeInterval[key] && val.Amount >= threshold[key].Val && val.State == 0 {
			val.State = 1
			this.Update(this)
		}
	}
	return
}

// jackpot小组：添加钱
func (this *JGroup) GMAddBonus(tid, amount int64) {
	this.rw.Lock()
	defer this.rw.Unlock()

	if val, ok := this.MBonus[tid]; ok {
		val.Amount += amount
		val.State = 1
		this.Update(this)
	}
	return
}
